import os, datetime
from lxml import etree
from enum import Enum
from selenium.webdriver.common.by import By
from support.network.browser import Browser
from support.dbms.helper import DBMS

class QUOTE:
    TAG = "QUOTE"
    HOMEPAGE = "http://quote.eastmoney.com/center/hszs.html"
    DATABASE_NAME = "stock"
    TABLE_NAME_DATE = "date"
    TABLE_NAME_QUOTE_VALUES = "quotevalues"
    TABLE_NAME_QUOTE_INFO = "quoteinfo"
    TABLE_NAME_QUOTE_IN_DAY = "quoteinday"
    TABLE_NAME_QUOTE_TURNING_POINT = "quotetp"
    DIRECT_UP = 1
    DIRECT_KEEP = 0
    DIRECT_DOWN = -1
    RESOURCE_MAP = {
        "CODE":"代码",
        "NAME":"名称",
        "PRICE":"最新价",
        "CHANGE":"涨跌额",
        "CHANGEP":"涨跌幅",
        "TURNOVER":"成交量",
        "BUSINESS":"成交额",
        "CLOSE":"昨收",
        "OPEN":"今开"
    }
    MARKETING = Enum('MARKETING', {
        'KEY' : 'hszs_hszyzs_simple-table',
        'SH' : 'hszs_shxlzs_simple-table',
        'SZ' :'hszs_szxlzs_simple-table'
    })
    __instance__ = None
    def __new__(cls, *args, **kwargs):
        if(not cls.__instance__): cls.__instance__ = object.__new__(cls)
        return cls.__instance__

    def getInstance():
        return QUOTE.__instance__

    def getTables(self):
        return [
            {"name":QUOTE.TABLE_NAME_QUOTE_INFO, "keys":[
                {"label":"CODE", "type":"INT"},
                {"label":"NAME", "type":"TEXT"},
                {"label":"MARKETING", "type":"TEXT"}
            ]},
            {"name":QUOTE.TABLE_NAME_QUOTE_VALUES, "keys":[
                {"label":"QID", "type":"INT"},
                {"label":"DID", "type":"INT"},
                {"label":"PRICE", "type":"FLOAT"},
                {"label":"CHANGE", "type":"FLOAT"},
                {"label":"CHANGEP", "type":"FLOAT"},
                {"label":"TURNOVER", "type":"TEXT"},
                {"label":"BUSINESS", "type":"TEXT"},
                {"label":"CLOSE", "type":"TEXT"},
                {"label":"OPEN", "type":"TEXT"}
            ]},
            {"name":QUOTE.TABLE_NAME_QUOTE_TURNING_POINT, "keys":[
                {"label":"QID", "type":"INT"},
                {"label":"DID", "type":"INT"},
                {"label":"PRICE", "type":"FLOAT"},
                {"label":"DIRECT", "type":"INT"},
                {"label":"TIME","type":"TIME" }
            ]},
            {"name":QUOTE.TABLE_NAME_DATE, "keys":[
                {"label":"DATE", "type":"DATE"},
                {"label":"TIME", "type":"TIME"}
            ]}
]

    def __fetch__(self, head):
        values = []
        for row in head.xpath('.//tr'):
            value = []
            columns = row.xpath('.//th')
            if(len(columns) == 0):columns = row.xpath('.//td')
            for cell in columns:
                span = cell.xpath('.//span')
                herf = cell.xpath('.//a')
                if(len(span) == 1):
                    value.append(span[0].text)
                elif(len(herf) == 1):
                    value.append(herf[0].text)
                else:
                    value.append(cell.text)
            values.append(value)
        return values

    def __fetchTable__(self, html, marketing):
        table = html.xpath('//table[@id="{}"]'.format(marketing.value))
        ret = []
        title = None
        data = None
        if(len(table) == 1):
            head = table[0].xpath('.//thead')
            body = table[0].xpath('.//tbody')
            if(len(head) == 1):
                title = self.__fetch__(head[0])
            if(len(body) == 1):
                data = self.__fetch__(body[0])
            for row in data:
                value = {}
                for index in range(0, len(title[0]) - 1):
                    value[title[0][index]] = row[index]
                ret.append(value)
        print(marketing.value, len(table), ret)
        return ret

    def fetch(self, oper):
        dateid, now = self.__prepare__(oper)
        tabid = None
        browser = Browser("http://{}:4444".format(os.environ.get("SELENIUM_HUB_HOST")), Browser.TYPE_EDGE)
        # browser = Browser(Browser.TYPE.chrome, version='132.0.6834.83', binpath='C:/Users/51101/AppData/Roaming/secoresdk/360se6/Application/360se.exe')
        try:
            tabid, html = browser.open(QUOTE.HOMEPAGE, timeout=10, waitConditions=[{"type":Browser.ELEMENT_VISIBLE, "element":(By.ID, 'mainc')}])
            orgData = etree.HTML(html)
            for marketing in QUOTE.MARKETING:
                value = self.__fetchTable__(orgData, marketing)
                print(marketing, value)
                for cell in value:
                    self.__autoSave__(oper, dateid, marketing, cell, now)
                    # print(self.__assemble__(cell))
        finally:
            if(tabid): browser.close(tabid)
            browser.exit()

    def autoTest(self):
        browser = Browser(Browser.TYPE.chrome, version='132.0.6834.83', binpath='C:/Users/51101/AppData/Roaming/secoresdk/360se6/Application/360se.exe')
        tabid = None
        try:
            tabid, html = browser.open(QUOTE.HOMEPAGE, timeout=10, waitConditions=[{"type":Browser.ELEMENT_VISIBLE, "element":(By.ID, 'mainc')}])
            orgData = etree.HTML(html)
            for marketing in QUOTE.MARKETING:
                value = self.__fetchTable__(orgData, marketing)
                for cell in value:
                    print(self.__assemble__(cell))
        except Exception as e:
            print(str(e))
        finally:
            if(tabid): browser.close(tabid)
            browser.exit()

    def __autoCreateQuoteInfo(self, oper, code, name, marketing):
        qid = None
        ret = DBMS.query(oper, QUOTE.TABLE_NAME_QUOTE_INFO, {"ID":None, "CODE":code, "NAME":name, "MARKETING":marketing.value})
        if(ret):qid = ret[0]["ID"]
        if(not qid):qid = DBMS.insert(oper, QUOTE.TABLE_NAME_QUOTE_INFO, {"CODE":code, "NAME":name, "MARKETING":marketing.value})
        return qid

    def __prepare__(self, oper):
        dateid = None
        current_datetime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        dateinfo = current_datetime.split(' ')
        ret = DBMS.query(oper, QUOTE.TABLE_NAME_DATE, {"ID":None, "DATE": dateinfo[0], "TIME": None}) 
        if(ret):dateid =ret[0]["ID"]
        if(not dateid):dateid = DBMS.insert(oper, QUOTE.TABLE_NAME_DATE, {"DATE":dateinfo[0], "TIME":dateinfo[1]})
        return dateid,dateinfo[1]

    def __autoSave__(self, oper, dateid, marketing, data, now):
        vid = None
        lastrecord = None
        data = self.__assemble__(data)
        qid = self.__autoCreateQuoteInfo(oper, data["CODE"], data["NAME"], marketing)
        ret = DBMS.query(oper, QUOTE.TABLE_NAME_QUOTE_VALUES, {"DID":dateid, "QID":qid, "ID":None})
        if(ret):vid = ret[0]["ID"]
        data.pop("CODE")
        data.pop("NAME")
        if(vid):
            DBMS.update(oper, QUOTE.TABLE_NAME_QUOTE_VALUES, data, {"ID":vid})
        else:
            vid = DBMS.insert(oper, QUOTE.TABLE_NAME_QUOTE_VALUES, data)
        price = float(data["PRICE"])
        today = DBMS.query(oper, QUOTE.TABLE_NAME_QUOTE_TURNING_POINT, {"ID":None, "QID":qid, "DID":dateid, "PRICE":None, "DIRECT":None})
        if(today): lastrecord = today[-1]
        if(not today): lastrecord = {"DIRECT":QUOTE.DIRECT_KEEP, "PRICE":price}
        turningData  = self.__getTurningData__(float(lastrecord["PRICE"]), lastrecord["DIRECT"], price, now)
        if(not today or turningData["DIRECT"] != lastrecord["DIRECT"]):
            turningData["QID"] = qid
            turningData["DID"] = dateid
            DBMS.insert(oper, QUOTE.TABLE_NAME_QUOTE_TURNING_POINT, turningData)
        else:
            DBMS.update(oper, QUOTE.TABLE_NAME_QUOTE_TURNING_POINT, turningData, {"ID":lastrecord["ID"]})

    def __getTurningData__(self, lastprice, lastdirect, currentprice, now):
        currentdirect = lastdirect
        if(currentprice < lastprice):
            currentdirect = QUOTE.DIRECT_DOWN
        elif(currentprice > lastprice):
            currentdirect = QUOTE.DIRECT_UP
        elif(lastdirect == QUOTE.DIRECT_KEEP):
            currentdirect = QUOTE.DIRECT_KEEP
        return {"DIRECT":currentdirect, "PRICE":currentprice, "TIME":now}

    def __assemble__(self, data):
        values = {}
        for key in QUOTE.RESOURCE_MAP:
            values[key] = data[QUOTE.RESOURCE_MAP[key]]
        changep = values["CHANGEP"].replace('%', '').strip()
        if(changep == '-'):
            values.pop("CHANGEP")
        else:
            values["CHANGEP"] = float(changep)/100
        return values
    
    def getData(self, num, *, year, month, day):
        pass
